package org.custom.spring.boot.security.filters.abstracts;

import org.custom.spring.boot.security.service.SecurityFilterChainManager;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Spring-Security 统一拦截器父类
 *
 * @author LiKun
 */
public abstract class AbstractUnityCommonFilter extends OncePerRequestFilter {
    @Resource
    private SecurityFilterChainManager securityFilterChainManager;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 请求是否被允许继续向下执行 || 前置回调处理器
        boolean requestAllowed2Proceed = this.preRequestFilterCallback(request, response, chain);

        // 执行拦截器业务逻辑
        if (requestAllowed2Proceed && !securityFilterChainManager.whetherTheInterceptorChainHandlesTheRequest(request.getRequestURI())) {
            requestAllowed2Proceed = this.requestFilterLogicalProcess(request, response, chain);
        }

        // 后置回调处理器
        if (requestAllowed2Proceed && this.afterRequestFilterCallback(request, response, chain)) {
            // 请求继续向下执行
            chain.doFilter(request, response);
        }
    }

    /**
     * 自定义拦截器逻辑处理，继承者需要重写该方法
     *
     * @param request  请求
     * @param response 响应
     * @param chain    拦截器链
     *
     * @return 请求是否被允许继续执行
     *
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    protected abstract boolean requestFilterLogicalProcess(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException;

    /**
     * 拦截器前置回调
     *
     * @param request  请求
     * @param response 响应
     * @param chain    拦截器链
     *
     * @return 请求是否被允许继续执行
     */
    protected boolean preRequestFilterCallback(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
        return true;
    }

    /**
     * 拦截器后置回调
     *
     * @param request  请求
     * @param response 响应
     * @param chain    拦截器链
     *
     * @return 请求是否被允许继续执行
     */
    protected boolean afterRequestFilterCallback(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
        return true;
    }
}
